/*
 * The MIT License
 *
 * Copyright 2014 Nathan Templon.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package tester;

import aero.fluid.FluidState;
import aero.fluid.IdealGas;
import aero.fluid.IdealGasState;
import dynamics.airplane.RocketPlane;
import dynamics.airplane.RocketPlaneParameters;
import dynamics.analysis.simulation.ExitCondition;
import dynamics.analysis.simulation.PitchOverExitCondition;
import dynamics.analysis.simulation.PitchOverRecorder;
import dynamics.analysis.simulation.Simulation;
import dynamics.analysis.simulation.TimeExitCondition;
import com.jupiter.ganymede.math.geometry.Angle;
import com.jupiter.ganymede.math.geometry.Angle.AngleType;
import com.jupiter.ganymede.math.geometry.Angle.TrigFunction;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import javax.swing.JOptionPane;
import propulsion.rocket.HobbyRocketEngine;
import util.PhysicalConstants;

/**
 *
 * @author nathant
 */
public class TestForm extends javax.swing.JFrame {

    /**
     * Creates new form TestForm
     */
    public TestForm() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        contentPanel = new javax.swing.JPanel();
        simulateButton = new javax.swing.JButton();
        enginePanel = new javax.swing.JPanel();
        rocketEngineLabel = new javax.swing.JLabel();
        engineTextField = new javax.swing.JTextField();
        fillerPanel = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("nFACT");
        setMinimumSize(new java.awt.Dimension(500, 300));

        contentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(3, 3, 3, 3));
        contentPanel.setLayout(new java.awt.GridBagLayout());

        simulateButton.setText("Run Simulation");
        simulateButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                simulateButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        contentPanel.add(simulateButton, gridBagConstraints);

        enginePanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Engine Selection"));
        enginePanel.setLayout(new java.awt.GridBagLayout());

        rocketEngineLabel.setFont(new java.awt.Font("Dialog", 0, 10)); // NOI18N
        rocketEngineLabel.setText("Rocket Engine");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        enginePanel.add(rocketEngineLabel, gridBagConstraints);

        engineTextField.setText("G-78");
        engineTextField.setToolTipText("");
        engineTextField.setEnabled(false);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        enginePanel.add(engineTextField, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        enginePanel.add(fillerPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 0.2;
        contentPanel.add(enginePanel, gridBagConstraints);

        getContentPane().add(contentPanel, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void simulateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_simulateButtonActionPerformed
        ExitCondition exit;

        RocketPlaneParameters prms = new RocketPlaneParameters();
        prms.setAspectRatio(4);
        prms.setCBar(0.6708);
        prms.setCd0(0.023);
        prms.setClAlpha(4.997);
        prms.setAlphaZeroLift(new Angle(-2.0933, AngleType.DEGREES));
        prms.setClDeltaE(0.3014);
        prms.setClQ(11.77);
        prms.setCpm0(-0.0499);
        prms.setCpmAlpha(-0.9668);
        prms.setCpmDeltaE(1.1708);
        prms.setCpmQ(-25.386);
        prms.setIyy(0.0764);
        prms.setBaseMass(2.28 / PhysicalConstants.GRAVITY_ACCELERATION);
        prms.setRocketEngine(HobbyRocketEngine.F40);
        prms.setSRef(1.8);
        prms.setSpanEfficiency(0.87);
        prms.setZThrust(0.0);

        String outputFolder = "/home/nathan/nFACT/";
//        String outputFolder = "D:\\nFACT\\";
        DecimalFormat format = new DecimalFormat("0.0000");
        StringBuilder summary = new StringBuilder();

        summary.append("Pitch Over:").append(System.lineSeparator());
        this.performPitchOverSimulation(prms, outputFolder, summary, format);
//        this.runCpm0Sweep(0.0, -0.1, 21, prms, outputFolder, summary, format);
//        this.runElevatorTest(new Angle(10, AngleType.DEGREES), 150.0, prms, outputFolder, summary, format);
        
//        summary.append("Elevator Test with Airspeed Sweep:").append(System.lineSeparator());
//        this.runElevatorSweep(40.0, 120.0, 21, new Angle(10, AngleType.DEGREES), prms, outputFolder, summary, format);
        
        summary.append("Impulse Response:").append(System.lineSeparator());
        this.performImpulseSimulation(prms, outputFolder, summary, format);

//        summary.append("Low-CPM0 Pitch Over Check:").append(System.lineSeparator());
//        this.performManualPitchOverTest(prms, outputFolder, summary, format);
        
        File summaryFile = new File(outputFolder + "summary.txt");
        try (FileWriter fw = new FileWriter(summaryFile)) {
            try (PrintWriter pw = new PrintWriter(fw)) {
                pw.println(summary.toString());
            }
        }
        catch (IOException ex) {

        }

        JOptionPane.showMessageDialog(this, "Simulation Complete!");
    }//GEN-LAST:event_simulateButtonActionPerformed

    private void performPitchOverSimulation(RocketPlaneParameters params, String outputFolder, StringBuilder summary, DecimalFormat format) {
//        AeroSystemState initialState = new AeroSystemState();
//        initialState.set(AeroSystemState.ANGULAR_POS, new Angle(89.5, Angle.AngleType.DEGREES));
//        initialState.set(AeroSystemState.ANGULAR_VEL, 0.0);
//        initialState.set(AeroSystemState.X_POS, 0.0);
//        initialState.set(AeroSystemState.X_VEL, 0.0);
//        initialState.set(AeroSystemState.Z_POS, 0.0);
//        initialState.set(AeroSystemState.Z_VEL, 0.1);
//        FluidState fluid = new IdealGasState(new IdealGas(28.97, 1.4), 95.0 + 459.0, 2018.68); // Air on a hot day
//        initialState.set(AeroSystemState.FLUID_STATE, fluid);
//        params.setInitialState(initialState);
//
//        RocketPlane system = new RocketPlane(params);
//        ExitCondition<AeroSystemState> exit = new PitchOverExitCondition();
//
//        File file = new File(outputFolder + "nFACT-PitchSim-Nominal-F40.csv");
//        PitchOverRecorder recorder = new PitchOverRecorder(file, 100);
//
//        Simulation sim = new Simulation(system, exit, recorder, 0.0005);
//        sim.run();
//
//        summary.append("\tPitch Over Summary:").append(System.lineSeparator());
//        summary.append("\t\tMax Speed: ").append(format.format(recorder.getMaxSpeed())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tBurnout before Pitch Over: ").append(recorder.getSimulationTime() > 5.4).append(System.lineSeparator());
//        summary.append("\t\tFinal Speed: ").append(format.format(recorder.getFinalVelocity())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tFinal Theta: ").append(format.format(recorder.getFinalTheta().getMeasure(AngleType.DEGREES)))
//                .append(" degrees").append(System.lineSeparator());
//        summary.append("\t\tMax Altitude: ").append(format.format(recorder.getMaxAltitude())).append(" ft").append(System.lineSeparator());
//        summary.append("\t\tCritical Normal Load Factor: ").append(format.format(recorder.getMinNormalLoadFactor())).append(System.lineSeparator());
//        summary.append("\t\tMax Axial Load Factor: ").append(format.format(recorder.getMaxAxialLoadFactor())).append(System.lineSeparator());
    }

    private void runCpm0Sweep(double start, double end, int numSteps, RocketPlaneParameters params, String outputFolder, StringBuilder summary, DecimalFormat format) {
//        AeroSystemState initialState;
//        FluidState fluid;
//        RocketPlane system;
//        ExitCondition<AeroSystemState> exit;
//
//        double initialCpm0 = params.getCpm0();
//        double incPerStep = (end - start) / (numSteps - 1);
//
//        // CPM0 sweeps
//        for (int i = 0; i < numSteps; i++) {
//            double cm0 = start + ((double) i) * incPerStep;
//            params.setCpm0(cm0);
//            initialState = new AeroSystemState();
//            initialState.set(AeroSystemState.ANGULAR_POS, new Angle(89.5, Angle.AngleType.DEGREES));
//            initialState.set(AeroSystemState.ANGULAR_VEL, 0.0);
//            initialState.set(AeroSystemState.X_POS, 0.0);
//            initialState.set(AeroSystemState.X_VEL, 0.0);
//            initialState.set(AeroSystemState.Z_POS, 0.0);
//            initialState.set(AeroSystemState.Z_VEL, 0.1);
//            fluid = new IdealGasState(new IdealGas(28.97, 1.4), 95.0 + 459.0, 2018.68); // Air on a hot day
//            initialState.set(AeroSystemState.FLUID_STATE, fluid);
//
//            params.setInitialState(initialState);
//            system = new RocketPlane(params);
//
//            File file = new File(outputFolder + "simulation-cpm0_" + format.format(cm0) + ".csv");
//            PitchOverRecorder recorder = new PitchOverRecorder(file, 100);
//            exit = new PitchOverExitCondition();
//
//            Simulation sim = new Simulation(system, exit, recorder, 0.0005);
//            sim.run();
//
//            summary.append("\tCase CPM0 = ").append(format.format(cm0)).append(":").append(System.lineSeparator());
//            summary.append("\t\tMax Speed: ").append(format.format(recorder.getMaxSpeed())).append(" ft/s").append(System.lineSeparator());
//            summary.append("\t\tBurnout before Pitch Over: ").append(recorder.getSimulationTime() > 5.4).append(System.lineSeparator());
//            summary.append("\t\tFinal Speed: ").append(format.format(recorder.getFinalVelocity())).append(" ft/s").append(System.lineSeparator());
//            summary.append("\t\tFinal Theta: ").append(format.format(recorder.getFinalTheta().getMeasure(AngleType.DEGREES)))
//                    .append(" degrees").append(System.lineSeparator());
//            summary.append("\t\tMax Altitude: ").append(format.format(recorder.getMaxAltitude())).append(" ft").append(System.lineSeparator());
//            summary.append("\t\tCritical Normal Load Factor: ").append(format.format(recorder.getMinNormalLoadFactor())).append(System.lineSeparator());
//            summary.append("\t\tMax Axial Load Factor: ").append(format.format(recorder.getMaxAxialLoadFactor())).append(System.lineSeparator());
//        }
//        params.setCpm0(initialCpm0);
    }

    private void runElevatorSweep(double startSpeed, double endSpeed, int numSteps, Angle deflection, RocketPlaneParameters params, String outputFolder, StringBuilder summary, DecimalFormat format) {
        if (numSteps <= 1) {
            this.runElevatorTest(deflection, startSpeed, params, outputFolder, summary, format);
            return;
        }

        double incPerStep = (endSpeed - startSpeed) / (numSteps - 1);
        for (int i = 0; i < numSteps; i++) {
            double speed = startSpeed + incPerStep * i;
            this.runElevatorTest(deflection, speed, params, outputFolder, summary, format);
        }
    }

    private void runElevatorTest(Angle deflection, double initialVelocity, RocketPlaneParameters params, String outputFolder, StringBuilder summary, DecimalFormat format) {
//        Angle steadyStateAlpha = new Angle(5.5, AngleType.DEGREES);
//        double cl = 0.7;
//        double cd = 0.049;
//        Angle fpa = new Angle(-1.0 * (cd / cl), TrigFunction.TANGENT);
//        Angle theta = fpa.add(steadyStateAlpha);
//
//        AeroSystemState initialState = new AeroSystemState();
//        initialState.set(AeroSystemState.ANGULAR_POS, theta);
//        initialState.set(AeroSystemState.ANGULAR_VEL, 0.0);
//        initialState.set(AeroSystemState.X_POS, 0.0);
//        initialState.set(AeroSystemState.X_VEL, initialVelocity * fpa.cos());
//        initialState.set(AeroSystemState.Z_POS, 0.0);
//        initialState.set(AeroSystemState.Z_VEL, initialVelocity * fpa.sin());
//        FluidState fluid = new IdealGasState(new IdealGas(28.97, 1.4), 95.0 + 459.0, 2018.68); // Air on a hot day
//        initialState.set(AeroSystemState.FLUID_STATE, fluid);
//
//        params.setInitialState(initialState);
//        params.setRocketEngine(HobbyRocketEngine.G25_POST_BURN);
//
//        RocketPlane system = new RocketPlane(params);
//        system.setElevatorDeflection(deflection);
//
//        Double defl = deflection.getMeasure(AngleType.DEGREES);
//        File file = new File(outputFolder + "simulation-deltaE_" + format.format(defl) + "-deg__vel_" + format.format(initialVelocity) + "-fps" + ".csv");
//        PitchOverRecorder recorder = new PitchOverRecorder(file, 20);
//        ExitCondition<AeroSystemState> exit = new TimeExitCondition<>(30.0);
//
//        Simulation sim = new Simulation(system, exit, recorder, 0.005);
//        sim.run();
//
//        summary.append("\tCase DeltaE = ").append(format.format(defl)).append("-deg:").append(System.lineSeparator());
//        summary.append("\t\tMax Speed: ").append(format.format(recorder.getMaxSpeed())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tFinal Speed: ").append(format.format(recorder.getFinalVelocity())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tFinal Theta: ").append(format.format(recorder.getFinalTheta().getMeasure(AngleType.DEGREES)))
//                .append(" degrees").append(System.lineSeparator());
//        summary.append("\t\tMax Altitude: ").append(format.format(recorder.getMaxAltitude())).append(" ft").append(System.lineSeparator());
//        summary.append("\t\tCritical Normal Load Factor: ").append(format.format(recorder.getMinNormalLoadFactor())).append(System.lineSeparator());
//        summary.append("\t\tMax Axial Load Factor: ").append(format.format(recorder.getMaxAxialLoadFactor())).append(System.lineSeparator());
    }

    private void performManualPitchOverTest(RocketPlaneParameters params, String outputFolder, StringBuilder summary, DecimalFormat format) {
//        AeroSystemState initialState = new AeroSystemState();
//        initialState.set(AeroSystemState.ANGULAR_POS, new Angle(89, Angle.AngleType.DEGREES));
//        initialState.set(AeroSystemState.ANGULAR_VEL, 0.0);
//        initialState.set(AeroSystemState.X_POS, 0.0);
//        initialState.set(AeroSystemState.X_VEL, 0.0);
//        initialState.set(AeroSystemState.Z_POS, 0.0);
//        initialState.set(AeroSystemState.Z_VEL, 150.0);
//        FluidState fluid = new IdealGasState(new IdealGas(28.97, 1.4), 95.0 + 459.0, 2018.68); // Air on a hot day
//        initialState.set(AeroSystemState.FLUID_STATE, fluid);
//        
//        params.setRocketEngine(HobbyRocketEngine.G25_POST_BURN);
//        params.setInitialState(initialState);
//
//        RocketPlane system = new RocketPlane(params);
//        system.setElevatorDeflection(new Angle(-5.0, AngleType.DEGREES));
//        ExitCondition<AeroSystemState> exit = new TimeExitCondition<>(30.0);
//
//        File file = new File(outputFolder + "Low-CPM0-PitchOver-Manual-Check.csv");
//        PitchOverRecorder recorder = new PitchOverRecorder(file, 100);
//
//        Simulation sim = new Simulation(system, exit, recorder, 0.0005);
//        sim.run();
//
//        summary.append("\tLow-CPM0 Pitch Over Summary:").append(System.lineSeparator());
//        summary.append("\t\tMax Speed: ").append(format.format(recorder.getMaxSpeed())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tBurnout before Pitch Over: ").append(recorder.getSimulationTime() > 5.4).append(System.lineSeparator());
//        summary.append("\t\tFinal Speed: ").append(format.format(recorder.getFinalVelocity())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tFinal Theta: ").append(format.format(recorder.getFinalTheta().getMeasure(AngleType.DEGREES)))
//                .append(" degrees").append(System.lineSeparator());
//        summary.append("\t\tMax Altitude: ").append(format.format(recorder.getMaxAltitude())).append(" ft").append(System.lineSeparator());
//        summary.append("\t\tCritical Normal Load Factor: ").append(format.format(recorder.getMinNormalLoadFactor())).append(System.lineSeparator());
//        summary.append("\t\tMax Axial Load Factor: ").append(format.format(recorder.getMaxAxialLoadFactor())).append(System.lineSeparator());
    }
    
    private void performImpulseSimulation(RocketPlaneParameters params, String outputFolder, StringBuilder summary, DecimalFormat format) {
//        Angle steadyStateAlpha = new Angle(5.1, AngleType.DEGREES);
//        double cl = 0.67;
//        double cd = 0.048;
//        Angle fpa = new Angle(-1.0 * (cd / cl), TrigFunction.TANGENT);
//        Angle theta = fpa.add(steadyStateAlpha);
//
//        AeroSystemState initialState = new AeroSystemState();
//        initialState.set(AeroSystemState.ANGULAR_POS, theta);
//        initialState.set(AeroSystemState.ANGULAR_VEL, 0.0);
//        initialState.set(AeroSystemState.X_POS, 0.0);
//        initialState.set(AeroSystemState.X_VEL, 44.0 * fpa.cos());
//        initialState.set(AeroSystemState.Z_POS, 0.0);
//        initialState.set(AeroSystemState.Z_VEL, 44.0 * fpa.sin() - 10.0);
//        FluidState fluid = new IdealGasState(new IdealGas(28.97, 1.4), 95.0 + 459.0, 2018.68); // Air on a hot day
//        initialState.set(AeroSystemState.FLUID_STATE, fluid);
//        
//        params.setRocketEngine(HobbyRocketEngine.G25_POST_BURN);
//        params.setInitialState(initialState);
//
//        RocketPlane system = new RocketPlane(params);
//        system.setElevatorDeflection(new Angle(6.7, AngleType.DEGREES));
//        ExitCondition<AeroSystemState> exit = new TimeExitCondition<>(30.0);
//
//        File file = new File(outputFolder + "Impulse-Response.csv");
//        PitchOverRecorder recorder = new PitchOverRecorder(file, 100);
//
//        Simulation sim = new Simulation(system, exit, recorder, 0.0005);
//        sim.run();
//
//        summary.append("\tImpulse Response Summary:").append(System.lineSeparator());
//        summary.append("\t\tMax Speed: ").append(format.format(recorder.getMaxSpeed())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tBurnout before Pitch Over: ").append(recorder.getSimulationTime() > 5.4).append(System.lineSeparator());
//        summary.append("\t\tFinal Speed: ").append(format.format(recorder.getFinalVelocity())).append(" ft/s").append(System.lineSeparator());
//        summary.append("\t\tFinal Theta: ").append(format.format(recorder.getFinalTheta().getMeasure(AngleType.DEGREES)))
//                .append(" degrees").append(System.lineSeparator());
//        summary.append("\t\tMax Altitude: ").append(format.format(recorder.getMaxAltitude())).append(" ft").append(System.lineSeparator());
//        summary.append("\t\tCritical Normal Load Factor: ").append(format.format(recorder.getMinNormalLoadFactor())).append(System.lineSeparator());
//        summary.append("\t\tMax Axial Load Factor: ").append(format.format(recorder.getMaxAxialLoadFactor())).append(System.lineSeparator());
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel.
         * For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        }
        catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(() -> {
            new TestForm().setVisible(true);
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel contentPanel;
    private javax.swing.JPanel enginePanel;
    private javax.swing.JTextField engineTextField;
    private javax.swing.JPanel fillerPanel;
    private javax.swing.JLabel rocketEngineLabel;
    private javax.swing.JButton simulateButton;
    // End of variables declaration//GEN-END:variables
}
